﻿#include "ipc_server.h"
#include <windows.h>
#include <thread>
#include "log_tool.h"
#include <cstring>
#include <cstdlib>

IpcServer::IpcServer()
    : _running(false)
{
    _input_handler = InputHanlderFactory::createHandler(); 
}

IpcServer::~IpcServer()
{
    stop();
}

bool IpcServer::start()
{
    if (_running)
        return true;
    _running = true;

    _input_handler->init(); // 初始化输入法处理逻辑，比如加载字典、初始化数据结构等

    // 启动监听线程
    return _acceptConnections();
}

void IpcServer::stop()
{
    if (!_running)
        return;
    _running = false;
    _input_handler->release(); // 释放输入法处理逻辑的资源
}

bool IpcServer::_acceptConnections()
{
    HANDLE hPipe; // 管道句柄
    SECURITY_ATTRIBUTES sa;
    SECURITY_DESCRIPTOR sd;
    InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
    SetSecurityDescriptorDacl(&sd, TRUE, NULL, FALSE); // 允许所有用户访问

    sa.nLength = sizeof(sa);
    sa.lpSecurityDescriptor = &sd;
    sa.bInheritHandle = FALSE;
    while (_running)
    {
        // 创建命名管道
        hPipe = CreateNamedPipeA(
            MENGYU_PIPE_NAME,
            PIPE_ACCESS_DUPLEX,
            PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
            PIPE_UNLIMITED_INSTANCES,
            MENGYU_PIPE_SIZE, // 输出缓冲区大小
            MENGYU_PIPE_SIZE, // 输入缓冲区大小
            0,                // 默认超时时间
            &sa);   // 添加安全属性参数

        if (hPipe == INVALID_HANDLE_VALUE)
        {
            LOG_ERROR("创建管道失败: %d", GetLastError());
            break;
        }

        // 等待客户端连接
        if (ConnectNamedPipe(hPipe, NULL) || GetLastError() == ERROR_PIPE_CONNECTED)
        {
            LOG_INFO("客户端已连接");
            // 为每个客户端创建独立线程处理
            std::thread clientThread(_handleClient, hPipe,_input_handler);
            clientThread.detach();
        }
        else
        {
            CloseHandle(hPipe);
        }
    }
    _running = false;
    return false;
}


bool IpcServer::_onSendLog(HANDLE hPipe,const char* data){
    LOG_INFO("[客户端日志] %s", data);
    MengYuWubiPipeMsg resp;
    resp.type = MengYuPipeMsgType::TYPE_LOG;

    DWORD bytesWritten;
    if (!WriteFile(hPipe, &resp, sizeof(resp), &bytesWritten, NULL))
    {
        LOG_ERROR("发送日志返回失败: %d", GetLastError());
        return false;
    }
    return true;
}

bool IpcServer::_onGetCandidate(HANDLE hPipe,std::shared_ptr<InputHandler>& input_handler, const char *data,int data_len){


    // 调用输入处理器获取候选词
    std::vector<std::string> candidates;
    input_handler->getCandidates(
        data, 
        candidates
    );

    // 构造响应数据
    unsigned char buffer[MENGYU_PIPE_SIZE];  
    MengYuWubiPipeMsg* resp = (MengYuWubiPipeMsg*)buffer;
    resp->type = MengYuPipeMsgType::TYPE_INPUT;

    // 填充候选词数据
    DWORD total_len = sizeof(MengYuWubiPipeMsg);   // 消息头和输入结果头的长度

    unsigned char* ptr = (unsigned char*)resp->data;
    for (const auto& candidate : candidates) {
        size_t len = candidate.size();  // 每个候选项的长度
        if(len > 255){ // 候选项长度超过255，截断
            len = 255;
        }
        if (total_len + len + 1 > MENGYU_PIPE_SIZE) break;  // 每一项数据，长度 + 词本身

        *ptr++ = static_cast<unsigned char>(len); //先写长度
        memcpy(ptr,candidate.data(),len); //再写数据
        ptr += len; //指针后移
    }
    total_len = ptr - buffer;

    // 发送响应
    DWORD bytesWritten;
    bool success = WriteFile(hPipe, resp, 
        total_len, 
        &bytesWritten, NULL);
    

    if (!success) {
        LOG_ERROR("发送候选词失败: %d", GetLastError());
        return false;
    }
    return true;
}

bool IpcServer::_onFlush(HANDLE hPipe,std::shared_ptr<InputHandler>& input_handler){
    return false;
}
bool IpcServer::_onShowUI(HANDLE hPipe,std::shared_ptr<InputHandler>& input_handler){
    return input_handler->showUI();
}

void IpcServer::_handleClient(HANDLE hPipe,std::shared_ptr<InputHandler> input_handler)
{
    char buffer[MENGYU_PIPE_SIZE + 1];
    MengYuWubiPipeMsg *msg = (MengYuWubiPipeMsg *)&buffer[0];
    DWORD bytesRead;

    while (true)
    {
        // 读取客户端消息
        if (!ReadFile(hPipe, buffer, MENGYU_PIPE_SIZE, &bytesRead, NULL))
        {
            if (GetLastError() == ERROR_BROKEN_PIPE)
            {
                LOG_INFO("客户端断开连接");
            }
            else
            {
                LOG_ERROR("读取数据失败: %d", GetLastError());
            }
            break;
        }

        buffer[bytesRead] = '\0';

        // 处理不同消息类型
        switch (msg->type)
        {
        case MengYuPipeMsgType::TYPE_LOG:
            _onSendLog(hPipe,msg->data);
            break;
        case MengYuPipeMsgType::TYPE_INPUT:
        {
            _onGetCandidate(hPipe, input_handler, msg->data,bytesRead - sizeof(MengYuWubiPipeMsg));
            break;
        }
        case MengYuPipeMsgType::TYPE_SHOWUI:
            input_handler->showUI(); // 显示UI
            break;
        default:
            LOG_WARNING("未知消息类型: %d", static_cast<int>(msg->type));
            break;
        }
    }

    // 清理资源
    // Flush the pipe to allow the client to read the pipe's contents 
    // before disconnecting. Then disconnect the pipe, and close the 
    // handle to this pipe instance. 
 
    FlushFileBuffers(hPipe); 
    DisconnectNamedPipe(hPipe);
    CloseHandle(hPipe);
}